from typing import Any, Awaitable, Callable, Dict, Union

from aiogram import BaseMiddleware
from aiogram.types import CallbackQuery, ErrorEvent, Message, Update
from fluentogram import TranslatorRunner

from src.bot.services.locale import Localizator
from src.core.exceptions.user import UserTgIdNotExist
from src.core.models.enums.user import LangCode
from src.database.services import UserService


class LocaleMiddleware(BaseMiddleware):
    def __init__(self, localizator: Localizator):
        self._loc: Localizator = localizator

    async def __call__(
        self,
        handler: Callable[[Update, Dict[str, Any]], Awaitable[Any]],
        event: Union[Message, Update, CallbackQuery],
        data: Dict[str, Any],
    ) -> Any:
        user_service: UserService = data["user_service"]
        if isinstance(event, Update):
            if event.message:
                user_id = event.message.from_user.id
            else:
                user_id = event.callback_query.from_user.id
        elif isinstance(event, ErrorEvent):
            if event.update.message:
                user_id = event.update.message.from_user.id
            else:
                user_id = event.update.callback_query.from_user.id
        else:
            user_id = event.from_user.id

        try:
            user = await user_service.get_user_by_telegram_id(user_id)
            user_lang = user.lang_code.value
        except UserTgIdNotExist:
            user_lang = LangCode.en

        _locale: TranslatorRunner = self._loc.get_by_locale(user_lang)

        data["localizator"] = self._loc
        data["locale"] = _locale

        return await handler(event, data)
